package com.sumer.psychology.comment.domain.model;

import com.sumer.psychology.common.Assert;
import com.sumer.psychology.common.domain.model.Author;
import com.sumer.psychology.common.domain.model.ConcurrencySafeEntity;

import java.util.Date;

/**
 * 评论
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/8/12
 * Time: 14:02
 */
public class Comment extends ConcurrencySafeEntity {
    private CommentId commentId;
    private CommentHost host;
    private String content;
    private Author author;
    private CommentType commentType;
    private Date createTime;
    private Date lastModifyTime;
    private CommentAvailability availability;

    /**
     * 创建评论
     *
     * @param identity    id
     * @param host        ref id
     * @param content     content
     * @param author      author
     * @param commentType type
     */
    public Comment(CommentId identity, CommentHost host, String content, Author author, CommentType commentType) {
        super();
        initialize(identity, host, content, author, commentType);

        apply();
    }

    public void apply() {
        apply(new CommentCreatedEvent(
                commentId(),
                host(),
                content(),
                author(),
                commentType()));
    }

    public void initialize(CommentId identity, CommentHost host, String content, Author author, CommentType commentType) {
        setCommentId(identity);
        setHost(host);
        setContent(content);
        setAuthor(author);
        setCommentType(commentType);
        setCreateTime(new Date());
        setAvailability(CommentAvailability.ACTIVE);
    }

    public Comment() {
        super();
    }

    /**
     * 修改评论
     *
     * @param content content
     */
    public void changeContent(String content) {
        setContent(content);
        setLastModifyTime(new Date());

        apply(new CommentChangedEvent(
                commentId(),
                content()));
    }

    /**
     * 删除评论
     */
    public void delete() {
        setAvailability(CommentAvailability.DELETED);
        setLastModifyTime(new Date());

        apply(new CommentDeletedEvent(commentId()));
    }

    public void setCommentId(CommentId commentId) {
        Assert.notNull(commentId, "唯一标志不能为空");
        Assert.notEmpty(commentId.identity(), "唯一标志不能为空");
        this.commentId = commentId;
    }

    private void setHost(CommentHost host) {
        Assert.notNull(host, "宿主不能为空");
        Assert.notEmpty(host.identity(), "宿主id不能为空");
        this.host = host;
    }

    protected void setContent(String content) {
        Assert.notEmpty(content, "评论内容不能为空");
        this.content = content;
    }

    private void setAuthor(Author author) {
        Assert.notNull(author, "评论者不能为空");
        Assert.notEmpty(author.identity(), "评论者id不能为空");
        this.author = author;
    }

    private void setCreateTime(Date createTime) {
        Assert.notNull(createTime, "创建日期不能为空");
        this.createTime = createTime;
    }

    private void setCommentType(CommentType commentType) {
        Assert.notNull(commentType, "评论类型不能为空");
        this.commentType = commentType;
    }

    private void setAvailability(CommentAvailability availability) {
        Assert.notNull(commentType, "可用性不能为空");
        this.availability = availability;
    }

    protected void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    public CommentId commentId() {
        return commentId;
    }

    public CommentHost host() {
        return host;
    }

    public String content() {
        return content;
    }

    public Author author() {
        return author;
    }

    public Date createTime() {
        return createTime;
    }

    public Date lastModifyTime() {
        return lastModifyTime;
    }

    public CommentType commentType() {
        return commentType;
    }

    public CommentAvailability availability() {
        return availability;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Comment comment = (Comment) o;

        if (author != null ? !author.equals(comment.author) : comment.author != null) return false;
        if (availability != comment.availability) return false;
        if (commentId != null ? !commentId.equals(comment.commentId) : comment.commentId != null) return false;
        if (commentType != comment.commentType) return false;
        if (content != null ? !content.equals(comment.content) : comment.content != null) return false;
        //if (createTime != null ? !createTime.equals(comment.createTime) : comment.createTime != null) return false;
        if (host != null ? !host.equals(comment.host) : comment.host != null) return false;
        /*if (lastModifyTime != null ? !lastModifyTime.equals(comment.lastModifyTime) : comment.lastModifyTime != null)
            return false;*/

        return true;
    }

    @Override
    public int hashCode() {
        int result = commentId != null ? commentId.hashCode() : 0;
        result = 31 * result + (host != null ? host.hashCode() : 0);
        result = 31 * result + (content != null ? content.hashCode() : 0);
        result = 31 * result + (author != null ? author.hashCode() : 0);
        result = 31 * result + (commentType != null ? commentType.hashCode() : 0);
        //result = 31 * result + (createTime != null ? createTime.hashCode() : 0);
        //result = 31 * result + (lastModifyTime != null ? lastModifyTime.hashCode() : 0);
        result = 31 * result + (availability != null ? availability.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Comment{" +
                "commentId=" + commentId +
                ", host=" + host +
                ", content='" + content + '\'' +
                ", author=" + author +
                ", commentType=" + commentType +
                ", createTime=" + createTime +
                ", lastModifyTime=" + lastModifyTime +
                ", availability=" + availability +
                '}';
    }
}
